package team.szm.scd.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import team.szm.scd.database.dto.CaseUploader;
import team.szm.scd.database.entity.*;
import team.szm.scd.database.mapper.*;
import team.szm.scd.database.vo.CaseVO;
import team.szm.scd.database.vo.DoctorVO;
import team.szm.scd.service.interfaces.ICaseService;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@EnableTransactionManagement
@Slf4j
public abstract class AbstractCaseService implements ICaseService {
    @Resource
    CaseMapper mapper;
    @Resource
    UserMapper userMapper;
    @Resource
    DoctorMapper doctorMapper;
    @Resource
    InsCaseHaveMapper insCaseHaveMapper;
    @Resource
    MdcCaseHaveMapper mdcCaseHaveMapper;
    @Resource
    InspectionTypeMapper inspectionTypeMapper;
    @Resource
    MedicineMapper medicineMapper;
    @Resource
    HospitalMapper hospitalMapper;

    @Override
    public Case fromRegister(String registerId) {
        QueryWrapper<Case> wrapper = new QueryWrapper<>();
        wrapper.eq("rid", registerId);
        return mapper.selectOne(wrapper);
    }

    @Override
    public Case fromId(String caseId) {
        return mapper.selectById(caseId);
    }

    @Override
    @Transactional
    public boolean updateInspectionFromId(String caseId, List<String> insIds) {
        QueryWrapper<InsCaseHave> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("cid", caseId);
        insCaseHaveMapper.delete(wrapper1);
        int num = 0;
        try {
            for (String insId : insIds) {
                num += insCaseHaveMapper.insert(new InsCaseHave(caseId, insId));
            }
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus()
                    .setRollbackOnly();
            log.info("数据库出现异常，进行回滚操作");
            return false;
        }
        if (num != insIds.size()) {
            TransactionAspectSupport.currentTransactionStatus()
                    .setRollbackOnly();
            log.info("数据插入数量错误，进行回滚操作");
            return false;
        }
        return true;
    }

    @Override
    @Transactional
    public boolean uploadCase(CaseUploader uploader, LocalDateTime now) {
        boolean result = true;
        try {
            //noinspection ConstantConditions
            do {
                Case case_ = uploader.getCase_();
                case_.setLastModifyTime(now);
                String caseId = case_.getId();
                if (mapper.replace(case_) <= 0) {
                    result = false;
                    break;
                }
                //这里对应插入新的病历，此时从数据库查找刚才创建的病例
                if (case_.getId() == null) {
                    QueryWrapper<Case> wrapper = new QueryWrapper<>();
                    wrapper.eq("rid", case_.getRegisterId());
                    caseId = mapper.selectOne(wrapper).getId();
                }
                QueryWrapper<InsCaseHave> wrapper1 = new QueryWrapper<>();
                wrapper1.eq("cid", caseId);
                insCaseHaveMapper.delete(wrapper1);
                int num = 0;
                for (String insId : uploader.getInspectionIds()) {
                    num += insCaseHaveMapper.insert(new InsCaseHave(caseId, insId));
                }
                if (num != uploader.getInspectionIds().size()) {
                    result = false;
                    break;
                }
                QueryWrapper<MdcCaseHave> wrapper2 = new QueryWrapper<>();
                wrapper2.eq("cid", caseId);
                mdcCaseHaveMapper.delete(wrapper2);
                num = 0;
                List<Integer> counts = uploader.getMedicineCounts();
                int index = 0;
                for (String mdcId : uploader.getMedicineIds()) {
                    num += mdcCaseHaveMapper.insert(
                            new MdcCaseHave(caseId, mdcId, counts.get(index++))
                    );
                }
                if (num != uploader.getMedicineIds().size()) {
                    result = false;
                    break;
                }
            } while (false);
        } catch (Exception e) {
            log.error(e.toString());
            result = false;
        }
        if (!result) {
            TransactionAspectSupport.currentTransactionStatus()
                    .setRollbackOnly();
            log.info("病历上传错误，进行回滚操作");
        }
        return result;
    }

    @Override
    @Transactional
    public List<CaseVO> getAllCaseFromUserId(String userId) {
        final User user = userMapper.selectById(userId);
        if (user == null) {
            return new ArrayList<>();
        }
        QueryWrapper<Case> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("uid", userId);
        List<Case> cases = mapper.selectList(wrapper1);
        try {
            return cases.parallelStream().map(case_ -> {
                CaseVO vo = new CaseVO();
                BeanUtils.copyProperties(case_, vo);
                vo.setAppointmentTime(vo.getLastModifyTime().toLocalDate());
                vo.setUserName(user.getName());
                vo.setUserAddress(user.getAddress());
                vo.setUserGender(user.getGender());
                String doctorId = vo.getDoctorId();
                DoctorVO doctor = doctorMapper.doctorsFromQueryWrapper(
                        new QueryWrapper<DoctorVO>().eq("did", doctorId)
                ).get(0);
                vo.setDoctorName(doctor.getName());
                vo.setDepartmentName(doctor.getDepartmentName());
                vo.setHospitalName(hospitalMapper.selectById(doctor.getHospitalId()).getName());
                vo.setInspections(inspectionTypeMapper.fromCaseId(vo.getId()));
                vo.setMedicines(medicineMapper.fromCaseId(vo.getId()));
                return vo;
            }).collect(Collectors.toList());
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus()
                    .setRollbackOnly();
            log.error(e.toString());
            return new ArrayList<>();
        }
    }
}
